#include "kraw.h"
#include "runtime.h"
#include "meshes.h"

//#include "Direct3D9/D3D9Display.h"
//#include "Direct3D9/D3D9Shader.h"

using namespace Kraw;

//data structures

//An application that loads a scene from an Xml file,
//displays it and lets you manipulate it from an onscreen console
class ViewApp : public App
{
public:
	ViewApp();

    MeshSource* pMeshSrc;
    Mesh* pMesh;
    
//    D3D9Shader* pVertexShader;

    matrix44 matWorld;
    matrix44 matView;
    matrix44 matProj;

	float yaw;
};

//APPLICATION
App* CreateApp()
{
    return new ViewApp;
}

//constructor
ViewApp::ViewApp() :
	pMeshSrc(0),
	pMesh(0),
//	pVertexShader(0),
	yaw(0.f)
{
}

//initialization
void App::Init()
{
    //load scene from Xml file

//    Mesh* mesh = new N3D2Mesh( "models/cube.n3d2" );
    ViewApp* self = (ViewApp*) this;
    self->pMeshSrc = new CubeMesh;

	self->matWorld = identity4();
    self->matView = lookAtLh( vector3(0.f, 3.f, -5.f), vector3(0.f, 0.f, 0.f), vector3(0.f, 1.f, 0.f) );
	self->matProj = perspectiveFovLh( PI/4.f, 4.f/3.f, 1.f, 100.f );

    //SetWorkingDirectory();
}

bool App::Open()
{
    //load resources using open display, traverse down scene hierarchy
    ViewApp* self = (ViewApp*) this;
    self->pMesh = pDisplay->LoadMesh( self->pMeshSrc );

	//TEMP-
	//D3D9Display* pD3D9Display = (D3D9Display*) pDisplay;
	//self->pVertexShader = pD3D9Display->LoadVertexShader( "..\\data\\shaders\\default.hlsl", "vsMain" );

    return self->pMesh != 0;
}

void App::Close()
{
    //unload resources
    ViewApp* self = (ViewApp*) this;
    delete self->pMesh;
    delete self->pMeshSrc;
    
    //TEMP-
//    delete self->pVertexShader;
}

bool App::Tick(float frameTime)
{
    //update game state
    ViewApp* self = (ViewApp*) this;

	//angle in radians- 2*PI (1 Hz)
    float deltaYaw = frameTime * ( 2.0f * PI ) / 1000.0f;
	self->yaw += deltaYaw / 4.f;
    self->matWorld = rotateZ(self->yaw);

    return true;
}

void App::Draw()
{
    //render
    ViewApp* self = (ViewApp*) this;

    //set view transform
	this->pDisplay->SetTransform( Display::World, self->matWorld );
	this->pDisplay->SetTransform( Display::View, self->matView );
	this->pDisplay->SetTransform( Display::Projection, self->matProj );

	//set shader and transforms
	//D3D9Display* pD3D9Display = (D3D9Display*) pDisplay;
	//matrix44 worldViewProj = pD3D9Display->GetTransform( Display::WorldViewProjection );
	//pD3D9Display->SetShader( self->pVertexShader );
	//pD3D9Display->SetShaderTransform( "view_proj_matrix", worldViewProj );

    //draw mesh
    this->pDisplay->DrawMesh( self->pMesh );
}
